import csv

from sam.util.convertUtil import list2dict
from sam.util.dateUtil import formatter_datetime
from sam.util.fileUtil import assert_is_expect_file_type
from sam.util.strUtil import contains_invalid


def _assert_single_row(d):
    if not d:
        raise RuntimeError("传入的参数不能为 空")
    if isinstance(d, list):
        dd = []
        dd.extend(d)
        while len(dd):
            pop = dd.pop()
            if pop:
                if type(pop) == list:
                    # print("两层嵌套")
                    return False
                else:
                    # print("单层嵌套")
                    return True
            else:
                # 继续循环
                pass

    else:
        s = f"错误的类型：{type(d)}. 只能处理 list"
        raise RuntimeError(s)


def _csv_write(target_file, mode, write_data, column: list = None):
    if not assert_is_expect_file_type(target_file, ".csv"):
        raise RuntimeError(f"文件 {target_file} 不是 有效的 csv 文件")
    if write_data:
        # 注意这里如果以‘w’的形式打开，每次写入的数据中间就会多一个空行，所以要用‘wb’
        with open(target_file, mode, newline='', encoding="utf-8") as f:
            writer = csv.writer(f, dialect='excel')
            if column:
                writer.writerow(column)
            if not _assert_single_row(write_data):
                # 这里如果需要写入多行，那么就采用循环进行循环输入就可以啦哈
                for line in write_data:
                    if line:
                        writer.writerow(line)
            else:
                writer.writerow(write_data)


def csv_write(target_file: str, write_data: list, optional: str = "append", column: list = None):
    if optional not in ["cover", "append"]:
        msg = f"仅支持 cover 和  append 模式， 不支持当前模式: {optional} "
        raise RuntimeWarning(msg)

    if "cover" == optional:
        csv_cover_write(target_file, write_data, column=column)
    elif "append" == optional:
        csv_append_write(target_file, write_data, column=column)


def csv_cover_write(target_file: str, write_data: list, column: list = None):
    '''
    覆盖的方式 写入文件
    :param column:
    :param target_file:
    :param write_data:
    :return:
    '''
    _csv_write(target_file, 'w', write_data, column=column)


def csv_append_write(target_file: str, write_data: list, column: list = None):
    '''
    追加的方式 写入文件
    :param column:
    :param target_file:
    :param write_data:
    :return:
    '''
    _csv_write(target_file, 'a+', write_data, column=column)


def csv_read(target_file
             , column: list = None
             , option: str = None
             , start: int = None
             , end: int = None
             , datetime_formatter: str = None
             , correct_func=None
             ):
    '''
    读csv文件的内容 返回 list
    :param correct_func:
    :param datetime_formatter:
    :param end:
    :param start:
    :param option:
    :param column:
    :param target_file:
    :return:
    '''
    if not assert_is_expect_file_type(target_file, "csv"):
        raise RuntimeError(f"文件 {target_file} 不是 有效的 csv 文件")
    if not option:
        option = "list"

    with open(target_file, "r", encoding="utf-8") as f:
        lines = csv.reader(f)
        new_lines = []
        if not start:
            start = 0
        if end:
            for num, line in enumerate(lines):
                if start <= num <= end:
                    if "list" == option:
                        if contains_invalid(line):
                            raise Exception(f"存在无效的数据 {line}")
                        new_lines.append(line)
                    elif "dict" == option and column:
                        res_dict = list2dict(column, line)
                        if correct_func:
                            correct_func(res_dict)
                        new_lines.append(res_dict)
                    else:
                        error_msg = f"不支持当前操作数 {option} 或 操作数为 dict 时, column 为 空"
                        raise RuntimeWarning(error_msg)
        else:
            for num, line in enumerate(lines):
                if num >= start:
                    new_line = formatter_datetime(line, datetime_formatter)
                    if "list" == option:
                        if contains_invalid(new_line):
                            raise Exception(f"存在无效的数据 {new_line}")
                        new_lines.append(new_line)
                    elif "dict" == option and column:
                        res_dict = list2dict(column, new_line)
                        if correct_func:
                            correct_func(res_dict)
                        new_lines.append(res_dict)
                    else:
                        error_msg = f"不支持当前操作数 {option} 或 操作数为 dict 时, column 为 空"
                        raise RuntimeWarning(error_msg)

        return new_lines
